import json
from tornado.web import RequestHandler, asynchronous
from tornado.auth import GoogleMixin
from tornado.websocket import WebSocketHandler

from util import Helpers, get_logger
import settings
from mandelbrot import get_tile

log = get_logger(__name__)

GLOBALS = {
    'sockets': [],
}


def get_routings():
    return [
        (r'/', MainHandler),
        (r'/rules', RulesHandler),
        (r'/cards', CardsHandler),
        (r'/post_list', PostListHandler),
        (r'/login', GoogleAuthHandler),
        (r'/logout', LogOutHandler),
        (r'/incoming', ClientSocketHandler),
        (r'/send_message', MessageDispatchHandler),
        (r'/style\.css', StyleHandler),
        (r'/mandelbrot/(.*)', MandelbrotHandler),
    ]


class CookieJar():
    def __init__(self, handler):
        self.handler = handler

    def __getattr__(self, name):
        cookie = self.handler.get_secure_cookie(name)
        if cookie:
            return cookie.decode('utf-8')


class BaseHandler(RequestHandler):
    menu = (
        ('/', 'Головна'),
        ('rules', 'Правила'),
        ('cards', 'Карти'),
        ('mandelbrot', 'mandelbrot'),
    )

    def initialize(self):
        self.h = Helpers(self)
        self.cookie = CookieJar(self)

    def render(self, template, **kwargs):
        super(BaseHandler, self).render(
            template,
            menu=self.menu,
            h=self.h,
            **kwargs
        )

    def get_current_user(self):
        if self.cookie.user_email:
            return {
                'email': self.cookie.user_email,
                'name': self.cookie.user_name,
                'locale': self.cookie.user_locale,
            }

    def set_current_user(self, user):
        if user:
            self.set_secure_cookie('user_email', user['email'])
            self.set_secure_cookie('user_name', user['name'])
            self.set_secure_cookie('user_locale', user['locale'])
        else:
            self.clear_cookie('user_email')

class StyleHandler(BaseHandler):
    def get(self):
        self.set_header('content-type', 'text/css')
        self.render('templates/style.css',
            black=settings.black,
            white=settings.white,
            gray=settings.gray,
        )

class LogOutHandler(BaseHandler):
    def get(self):
        self.set_current_user(None)
        self.redirect('/')

class GoogleAuthHandler(BaseHandler, GoogleMixin):
    @asynchronous
    def get(self):
        if self.get_current_user():
            self.redirect('/')
        if self.get_argument("openid.mode", None):
            self.get_authenticated_user(self.async_callback(self._on_auth))
            return
        self.authenticate_redirect()

    def _on_auth(self, user):
        if not user:
            raise tornado.web.HTTPError(500, "Google auth failed")
        self.set_current_user(user)
        self.redirect('/')
        self.finish()


class ClientSocketHandler(WebSocketHandler):
    def open(self):
        GLOBALS['sockets'].append(self)
        log.info("WebSocket opened")
        for socket in GLOBALS['sockets']:
            socket.write_message(json.dumps(dict(
                message='В чаті разом з вами присутні %s сокетів' % len(GLOBALS['sockets']),
                user='Система',
            )))

    def on_close(self):
        GLOBALS['sockets'].remove(self)
        log.info("WebSocket closed")
        for socket in GLOBALS['sockets']:
            socket.write_message(json.dumps(dict(
                message='В чаті разом з вами присутні %s сокетів' % len(GLOBALS['sockets']),
                user='Система',
            )))


class MessageDispatchHandler(BaseHandler):
    def get(self):
        user = self.get_current_user()
        package = dict(
            message=self.get_argument('message'),
            user=user and user['name'],
        )
        log.info('Dispatching "%s" to %s sockets' % (
            package, len(GLOBALS['sockets'])
        ))
        for socket in GLOBALS['sockets']:
            socket.write_message(json.dumps(package))
        self.write('Ok')


class MainHandler(BaseHandler):
    def get(self):
        user = self.get_secure_cookie("user")
        self.render(
            'templates/home.html',
            current_menu_item='/',
            user=user,
        )


class RulesHandler(BaseHandler):
    def get(self):
        self.render(
            'templates/rules.html',
            current_menu_item='rules',
        )


class CardsHandler(BaseHandler):
    def get(self):
        self.render(
            'templates/cards.html',
            current_menu_item='cards',
            cards_count=settings.cards_count,
        )


class PostListHandler(BaseHandler):
    def get(self):
        self.render(
            'templates/post_list.html',
            current_menu_item='post_list',
        )

class MandelbrotHandler(BaseHandler):
    def get(self, coords):
        xc, yc, d = map(float, coords.split('_'))
        d = d / 3
        tiles = []
        for y in (yc + d, yc, yc - d):
            row = []
            for x in (xc - d, xc, xc + d):
                row.append({
                    'href': '/mandelbrot/{}_{}_{}'.format(x, y, d),
                    'image': '/' + get_tile(x, y, d, 'static/mandelbrot/'),
                })
            tiles.append(row)
        self.render(
            'templates/mandelbrot.html',
            current_menu_item='mandelbrot',
            tiles=tiles,
        )
